Skill

Jackson এর জন্য Unit Testing

Java Technologies - জ্যাকসন (Jackson)
245

Jackson-এর মাধ্যমে JSON ডেটা প্রসেসিং সঠিকভাবে কাজ করছে কিনা তা নিশ্চিত করতে Unit Testing অপরিহার্য। Unit Testing এর জন্য সাধারণত JUnit এবং AssertJ এর মত টুল ব্যবহার করা হয়।


Unit Testing কীভাবে কাজ করে?

  1. JSON Serialization Validation: Object থেকে JSON স্ট্রিং তৈরি হচ্ছে কিনা তা পরীক্ষা করা।
  2. JSON Deserialization Validation: JSON স্ট্রিং থেকে Object সঠিকভাবে তৈরি হচ্ছে কিনা তা পরীক্ষা করা।
  3. Custom Serializer/Deserializer Validation: কাস্টম লজিক সঠিকভাবে কাজ করছে কিনা তা পরীক্ষা করা।
  4. Edge Case Handling: Null, Empty এবং Invalid JSON এর জন্য পরীক্ষা করা।

প্রয়োজনীয় টুল এবং ডিপেন্ডেন্সি

Maven ডিপেন্ডেন্সি

<dependencies>
    <!-- Jackson -->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.15.2</version>
    </dependency>

    <!-- JUnit -->
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter</artifactId>
        <version>5.10.0</version>
        <scope>test</scope>
    </dependency>

    <!-- AssertJ -->
    <dependency>
        <groupId>org.assertj</groupId>
        <artifactId>assertj-core</artifactId>
        <version>3.24.2</version>
        <scope>test</scope>
    </dependency>
</dependencies>

1. JSON Serialization Test

উদাহরণ:

import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;

public class JacksonSerializationTest {

    @Test
    public void testSerialization() throws Exception {
        // Arrange
        User user = new User(1, "John Doe", "john.doe@example.com");
        ObjectMapper objectMapper = new ObjectMapper();

        // Act
        String json = objectMapper.writeValueAsString(user);

        // Assert
        assertThat(json).contains("\"id\":1");
        assertThat(json).contains("\"name\":\"John Doe\"");
        assertThat(json).contains("\"email\":\"john.doe@example.com\"");
    }
}

// Model Class
class User {
    private int id;
    private String name;
    private String email;

    public User(int id, String name, String email) {
        this.id = id;
        this.name = name;
        this.email = email;
    }

    // Getters and Setters
}

2. JSON Deserialization Test

উদাহরণ:

import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;

public class JacksonDeserializationTest {

    @Test
    public void testDeserialization() throws Exception {
        // Arrange
        String json = "{\"id\":1,\"name\":\"John Doe\",\"email\":\"john.doe@example.com\"}";
        ObjectMapper objectMapper = new ObjectMapper();

        // Act
        User user = objectMapper.readValue(json, User.class);

        // Assert
        assertThat(user.getId()).isEqualTo(1);
        assertThat(user.getName()).isEqualTo("John Doe");
        assertThat(user.getEmail()).isEqualTo("john.doe@example.com");
    }
}

3. Custom Serializer Test

Custom Serializer:

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;

import java.io.IOException;

public class CustomUserSerializer extends JsonSerializer<User> {
    @Override
    public void serialize(User user, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        gen.writeStartObject();
        gen.writeStringField("userId", String.valueOf(user.getId()));
        gen.writeStringField("userName", user.getName());
        gen.writeEndObject();
    }
}

Test:

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;

public class CustomSerializerTest {

    @Test
    public void testCustomSerializer() throws Exception {
        // Arrange
        User user = new User(1, "John Doe", "john.doe@example.com");
        ObjectMapper objectMapper = new ObjectMapper();
        SimpleModule module = new SimpleModule();
        module.addSerializer(User.class, new CustomUserSerializer());
        objectMapper.registerModule(module);

        // Act
        String json = objectMapper.writeValueAsString(user);

        // Assert
        assertThat(json).contains("\"userId\":\"1\"");
        assertThat(json).contains("\"userName\":\"John Doe\"");
    }
}

4. Invalid JSON Test

উদাহরণ:

import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThatThrownBy;

public class InvalidJsonTest {

    @Test
    public void testInvalidJson() {
        // Arrange
        String invalidJson = "{ \"id\": 1, \"name\": \"John\", \"email\": 12345 }"; // Invalid email
        ObjectMapper objectMapper = new ObjectMapper();

        // Act & Assert
        assertThatThrownBy(() -> objectMapper.readValue(invalidJson, User.class))
                .isInstanceOf(Exception.class)
                .hasMessageContaining("Cannot deserialize value of type");
    }
}

5. Null Handling Test

উদাহরণ:

import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;

public class NullHandlingTest {

    @Test
    public void testNullFields() throws Exception {
        // Arrange
        User user = new User(1, null, null);
        ObjectMapper objectMapper = new ObjectMapper();

        // Act
        String json = objectMapper.writeValueAsString(user);

        // Assert
        assertThat(json).contains("\"id\":1");
        assertThat(json).doesNotContain("name");
        assertThat(json).doesNotContain("email");
    }
}

6. Testing with Arrays/Lists

উদাহরণ:

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;

import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;

public class ArrayDeserializationTest {

    @Test
    public void testArrayDeserialization() throws Exception {
        // Arrange
        String json = "[{\"id\":1,\"name\":\"John Doe\",\"email\":\"john.doe@example.com\"},"
                    + "{\"id\":2,\"name\":\"Jane Doe\",\"email\":\"jane.doe@example.com\"}]";
        ObjectMapper objectMapper = new ObjectMapper();

        // Act
        List<User> users = objectMapper.readValue(json, new TypeReference<List<User>>() {});

        // Assert
        assertThat(users).hasSize(2);
        assertThat(users.get(0).getName()).isEqualTo("John Doe");
        assertThat(users.get(1).getEmail()).isEqualTo("jane.doe@example.com");
    }
}

7. Edge Case Test

Null JSON:

@Test
public void testNullJson() {
    ObjectMapper objectMapper = new ObjectMapper();

    assertThatThrownBy(() -> objectMapper.readValue(null, User.class))
            .isInstanceOf(NullPointerException.class);
}

Empty JSON:

@Test
public void testEmptyJson() throws Exception {
    String emptyJson = "{}";
    ObjectMapper objectMapper = new ObjectMapper();

    User user = objectMapper.readValue(emptyJson, User.class);

    assertThat(user.getId()).isEqualTo(0);
    assertThat(user.getName()).isNull();
    assertThat(user.getEmail()).isNull();
}

  1. Jackson Unit Testing নিশ্চিত করে যে JSON ডেটা প্রসেসিং সঠিকভাবে কাজ করছে।
  2. Serialization, Deserialization, এবং Custom Serializer/Deserializer সঠিকভাবে পরীক্ষা করা যায়।
  3. Edge Cases এবং Invalid JSON হ্যান্ডল করার জন্য পরীক্ষা গুরুত্বপূর্ণ।
  4. AssertJ এবং JUnit ব্যবহার করে সহজেই Validation এবং Exception Management করা যায়।

Jackson এর সাথে Unit Testing API-এর নির্ভরযোগ্যতা এবং স্থায়িত্ব নিশ্চিত করে।

Content added By

Jackson এর জন্য Unit Test তৈরি করা

253

Jackson এর জন্য Unit Test তৈরি করতে আমরা সাধারণত JUnit এবং ObjectMapper ব্যবহার করি। Unit Test-এ আমরা Jackson-এর serialization (Java থেকে JSON) এবং deserialization (JSON থেকে Java) প্রক্রিয়াগুলো যাচাই করি।


Unit Test এর ধাপসমূহ

  1. Dependency Management: JUnit এবং Jackson এর প্রয়োজনীয় ডিপেন্ডেন্সি যোগ করা।
  2. Test Setup: ObjectMapper ইন্সট্যান্স তৈরি করা।
  3. Serialization Test: Java Object থেকে JSON-এ সঠিক রূপান্তর নিশ্চিত করা।
  4. Deserialization Test: JSON থেকে Java Object-এ সঠিক রূপান্তর নিশ্চিত করা।
  5. Edge Case Handling: অপ্রত্যাশিত বা ভুল ডেটার জন্য টেস্টিং।

Maven Dependencies

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.15.0</version>
</dependency>
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter</artifactId>
    <version>5.10.0</version>
    <scope>test</scope>
</dependency>

Java Model Class

import com.fasterxml.jackson.annotation.JsonProperty;

public class User {
    @JsonProperty("user_name")
    private String name;
    private int age;

    public User() {
    }

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // Getters এবং Setters
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        User user = (User) o;
        return age == user.age && name.equals(user.name);
    }
}

Unit Test Code

১. Serialization Test

import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;

public class UserSerializationTest {

    @Test
    public void testSerialization() throws Exception {
        // Arrange
        User user = new User("John Doe", 25);
        ObjectMapper objectMapper = new ObjectMapper();

        // Act
        String json = objectMapper.writeValueAsString(user);

        // Assert
        String expectedJson = "{\"user_name\":\"John Doe\",\"age\":25}";
        assertEquals(expectedJson, json);
    }
}

২. Deserialization Test

import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;

public class UserDeserializationTest {

    @Test
    public void testDeserialization() throws Exception {
        // Arrange
        String json = "{\"user_name\":\"John Doe\",\"age\":25}";
        ObjectMapper objectMapper = new ObjectMapper();

        // Act
        User user = objectMapper.readValue(json, User.class);

        // Assert
        User expectedUser = new User("John Doe", 25);
        assertEquals(expectedUser, user);
    }
}

৩. Edge Case Test

import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertThrows;

public class UserEdgeCaseTest {

    @Test
    public void testInvalidJson() {
        // Arrange
        String invalidJson = "{\"user_name\":\"John Doe\",\"age\":\"invalid\"}";
        ObjectMapper objectMapper = new ObjectMapper();

        // Act and Assert
        assertThrows(Exception.class, () -> objectMapper.readValue(invalidJson, User.class));
    }

    @Test
    public void testMissingField() throws Exception {
        // Arrange
        String partialJson = "{\"user_name\":\"John Doe\"}";
        ObjectMapper objectMapper = new ObjectMapper();

        // Act
        User user = objectMapper.readValue(partialJson, User.class);

        // Assert
        User expectedUser = new User("John Doe", 0); // Default age is 0
        assertEquals(expectedUser, user);
    }
}

৪. Custom Serializer/Deserializer Test

Custom Serializer
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;

import java.io.IOException;

public class CustomUserSerializer extends JsonSerializer<User> {
    @Override
    public void serialize(User user, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        gen.writeStartObject();
        gen.writeStringField("full_name", user.getName().toUpperCase());
        gen.writeNumberField("user_age", user.getAge());
        gen.writeEndObject();
    }
}
Custom Serializer Test
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;

public class CustomSerializerTest {

    @Test
    public void testCustomSerializer() throws Exception {
        // Arrange
        User user = new User("John Doe", 25);
        ObjectMapper objectMapper = new ObjectMapper();
        SimpleModule module = new SimpleModule();
        module.addSerializer(User.class, new CustomUserSerializer());
        objectMapper.registerModule(module);

        // Act
        String json = objectMapper.writeValueAsString(user);

        // Assert
        String expectedJson = "{\"full_name\":\"JOHN DOE\",\"user_age\":25}";
        assertEquals(expectedJson, json);
    }
}

পরীক্ষার কাভারেজ

  1. Serialization: Java Object → JSON।
  2. Deserialization: JSON → Java Object।
  3. Edge Cases: যেমন ভুল ডেটা টাইপ, মিসিং ফিল্ড।
  4. Custom Serializer/Deserializer।
  5. Exception Handling।

  1. JUnit: Jackson-এর serialization এবং deserialization প্রক্রিয়া যাচাই করার জন্য সহজ এবং কার্যকর।
  2. Edge Cases: ভুল JSON ডেটা এবং মিসম্যাচ ফিল্ডের জন্য পরীক্ষা করুন।
  3. Custom Logic: কাস্টম Serializer/Deserializer এর জন্য টেস্ট রাইটিং অত্যন্ত গুরুত্বপূর্ণ।
  4. Automation: Unit Test কোড Jackson-এর সাথে কাজ করার সময় সঠিকতা নিশ্চিত করে এবং বাগ কমায়।
Content added By

JUnit এবং Mockito এর সাথে Integration

193

Jackson ব্যবহার করে JSON ডেটা Serialize/Deserialize করার জন্য JUnit এবং Mockito দিয়ে টেস্টিং করা একটি সাধারণ পদ্ধতি। এই পদ্ধতিতে, JSON ডেটা হ্যান্ডলিং এবং API এর বেহেভিয়ার নিশ্চিত করতে ObjectMapper এবং মক করা সেবাগুলোর ওপর নির্ভর করে টেস্ট তৈরি করা হয়।


প্রয়োজনীয় Maven ডিপেনডেন্সি

<dependencies>
    <!-- JUnit -->
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter</artifactId>
        <version>5.10.0</version>
        <scope>test</scope>
    </dependency>

    <!-- Mockito -->
    <dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-core</artifactId>
        <version>5.4.0</version>
        <scope>test</scope>
    </dependency>

    <!-- Jackson -->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.15.2</version>
    </dependency>
</dependencies>

Step-by-Step Integration উদাহরণ

১. মডেল ক্লাস তৈরি করা

public class User {
    private String name;
    private int age;
    private String email;

    // Constructors, Getters, and Setters
    public User() {}

    public User(String name, int age, String email) {
        this.name = name;
        this.age = age;
        this.email = email;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}

২. JUnit দিয়ে Jackson টেস্ট করা

ObjectMapper ব্যবহার করে Serialization/Deserialization টেস্ট
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;

public class JacksonTest {

    @Test
    public void testSerialization() throws Exception {
        // Arrange
        User user = new User("Alice", 30, "alice@example.com");
        ObjectMapper mapper = new ObjectMapper();

        // Act
        String json = mapper.writeValueAsString(user);

        // Assert
        String expectedJson = "{\"name\":\"Alice\",\"age\":30,\"email\":\"alice@example.com\"}";
        assertEquals(expectedJson, json);
    }

    @Test
    public void testDeserialization() throws Exception {
        // Arrange
        String json = "{\"name\":\"Bob\",\"age\":25,\"email\":\"bob@example.com\"}";
        ObjectMapper mapper = new ObjectMapper();

        // Act
        User user = mapper.readValue(json, User.class);

        // Assert
        assertEquals("Bob", user.getName());
        assertEquals(25, user.getAge());
        assertEquals("bob@example.com", user.getEmail());
    }
}

৩. Mockito ব্যবহার করে Service Layer টেস্ট করা

Service Layer
import org.springframework.stereotype.Service;

@Service
public class UserService {
    public String getUserData(User user) {
        if (user.getAge() < 18) {
            return "User is a minor";
        }
        return "User is an adult";
    }
}
Mockito দিয়ে Service Layer টেস্ট
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.when;

public class UserServiceTest {

    @Test
    public void testGetUserData() {
        // Arrange
        UserService userService = Mockito.mock(UserService.class);
        User user = new User("Charlie", 17, "charlie@example.com");

        // Mocking the service method
        when(userService.getUserData(user)).thenReturn("User is a minor");

        // Act
        String result = userService.getUserData(user);

        // Assert
        assertEquals("User is a minor", result);
    }
}

৪. Spring Boot এবং Controller টেস্ট করা

Controller Layer
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/users")
public class UserController {

    @PostMapping
    public String createUser(@RequestBody User user) {
        return "User created: " + user.getName();
    }
}
MockMvc ব্যবহার করে Controller টেস্ট
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.test.web.servlet.MockMvc;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;

@WebMvcTest(UserController.class)
public class UserControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @Autowired
    private ObjectMapper objectMapper;

    @Test
    public void testCreateUser() throws Exception {
        // Arrange
        User user = new User("Alice", 30, "alice@example.com");
        String json = objectMapper.writeValueAsString(user);

        // Act & Assert
        mockMvc.perform(post("/api/users")
                .contentType("application/json")
                .content(json))
                .andExpect(status().isOk())
                .andExpect(content().string("User created: Alice"));
    }
}

৫. Test Coverage নিশ্চিত করা

  • Unit Test: মডেল ক্লাস এবং সার্ভিস লেয়ার টেস্ট করার জন্য JUnit ব্যবহার।
  • Mocking External Services: Mockito দিয়ে ডিপেন্ডেন্সি মক করা।
  • Integration Test: MockMvc দিয়ে Controller এবং API টেস্ট করা।
  • Serialization/Deserialization: Jackson এর ObjectMapper ব্যবহার করে নিশ্চিত করা যে JSON ফরম্যাট সঠিক।

  1. JUnit: JSON Serialization/Deserialization ভেরিফাই করতে ব্যবহার করা হয়।
  2. Mockito: ডিপেন্ডেন্সি মক করে সার্ভিস লেয়ার বা ডেটাবেস ইন্টারঅ্যাকশন টেস্ট করা হয়।
  3. Spring Boot Test Framework: MockMvc দিয়ে REST API টেস্ট করা।
  4. ObjectMapper: Jackson এর মাধ্যমে JSON ডেটার গুণগত মান নিশ্চিত করতে ব্যবহৃত হয়।
Content added By

Serialization এবং Deserialization এর Test Coverage

274

JSON Serialization এবং Deserialization Jackson-এর অন্যতম গুরুত্বপূর্ণ ফিচার। API বা ডেটা প্রসেসিং অ্যাপ্লিকেশনে ডেটা সঠিকভাবে হ্যান্ডল করার জন্য Serialization এবং Deserialization প্রক্রিয়ার সঠিকতা যাচাই করা অত্যন্ত গুরুত্বপূর্ণ। Test Coverage নিশ্চিত করার জন্য JUnit এবং Mocking Framework (যেমন Mockito) ব্যবহার করা হয়।


Serialization এবং Deserialization কী?

  • Serialization: Java Object কে JSON String-এ রূপান্তর করা।
  • Deserialization: JSON String কে Java Object-এ রূপান্তর করা।

Serialization এবং Deserialization Test Coverage কেন গুরুত্বপূর্ণ?

  1. ডেটা সঠিকভাবে JSON ফরম্যাটে রূপান্তর হচ্ছে কিনা তা যাচাই করা।
  2. JSON থেকে Java Object সঠিকভাবে তৈরি হচ্ছে কিনা তা নিশ্চিত করা।
  3. Missing Fields, Unknown Fields, এবং Invalid Data Handling নিশ্চিত করা।
  4. Custom Serializer/Deserializer ঠিকমতো কাজ করছে কিনা তা যাচাই করা।

1. Serialization Test Coverage

Serialization Test Case Example:

মডেল ক্লাস:
import com.fasterxml.jackson.annotation.JsonInclude;

@JsonInclude(JsonInclude.Include.NON_NULL) // Exclude null fields during serialization
public class User {
    public int id;
    public String name;
    public String email;

    public User(int id, String name, String email) {
        this.id = id;
        this.name = name;
        this.email = email;
    }
}
Serialization টেস্ট কোড:
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

public class SerializationTest {

    @Test
    public void testSerialization() throws Exception {
        User user = new User(101, "John Doe", null); // Null email should be excluded

        ObjectMapper objectMapper = new ObjectMapper();
        String json = objectMapper.writeValueAsString(user);

        // Validate JSON string
        assertTrue(json.contains("\"id\":101"));
        assertTrue(json.contains("\"name\":\"John Doe\""));
        assertFalse(json.contains("email")); // Email is null, so it should not be present
    }
}
আউটপুট:
Serialization Passed: JSON format is valid and excludes null fields.

2. Deserialization Test Coverage

Deserialization Test Case Example:

JSON String Example:
{
  "id": 101,
  "name": "John Doe",
  "email": "john.doe@example.com"
}
Deserialization টেস্ট কোড:
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

public class DeserializationTest {

    @Test
    public void testDeserialization() throws Exception {
        String json = """
        {
          "id": 101,
          "name": "John Doe",
          "email": "john.doe@example.com"
        }
        """;

        ObjectMapper objectMapper = new ObjectMapper();
        User user = objectMapper.readValue(json, User.class);

        // Validate Java Object
        assertEquals(101, user.id);
        assertEquals("John Doe", user.name);
        assertEquals("john.doe@example.com", user.email);
    }
}
আউটপুট:
Deserialization Passed: JSON fields correctly mapped to Java object.

3. Handling Missing and Unknown Fields

Test for Missing Fields:

@Test
public void testMissingFields() throws Exception {
    String json = """
    {
      "id": 101,
      "name": "John Doe"
    }
    """; // "email" is missing

    ObjectMapper objectMapper = new ObjectMapper();
    User user = objectMapper.readValue(json, User.class);

    // Validate Java Object
    assertEquals(101, user.id);
    assertEquals("John Doe", user.name);
    assertNull(user.email); // Email should be null
}

Test for Unknown Fields:

@Test
public void testUnknownFields() throws Exception {
    String json = """
    {
      "id": 101,
      "name": "John Doe",
      "unknownField": "extra data"
    }
    """; // Unknown field "unknownField"

    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); // Ignore unknown fields

    User user = objectMapper.readValue(json, User.class);

    // Validate Java Object
    assertEquals(101, user.id);
    assertEquals("John Doe", user.name);
}

4. Testing Custom Serializer and Deserializer

Custom Serializer:

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;

import java.io.IOException;

public class CustomNameSerializer extends JsonSerializer<String> {
    @Override
    public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        gen.writeString("Name: " + value);
    }
}

Serializer Test:

@Test
public void testCustomSerializer() throws Exception {
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.addMixIn(User.class, CustomSerializerMixin.class);

    User user = new User(101, "John Doe", null);
    String json = objectMapper.writeValueAsString(user);

    // Validate custom serialization
    assertTrue(json.contains("\"name\":\"Name: John Doe\""));
}

Mixin Class:

import com.fasterxml.jackson.databind.annotation.JsonSerialize;

public abstract class CustomSerializerMixin {
    @JsonSerialize(using = CustomNameSerializer.class)
    public String name;
}

5. Testing Error Scenarios

Invalid Data:

@Test
public void testInvalidData() {
    String invalidJson = """
    {
      "id": "invalid",
      "name": "John Doe"
    }
    """;

    ObjectMapper objectMapper = new ObjectMapper();

    assertThrows(JsonMappingException.class, () -> {
        objectMapper.readValue(invalidJson, User.class);
    });
}

Null or Empty JSON:

@Test
public void testEmptyJson() throws Exception {
    String emptyJson = "{}";

    ObjectMapper objectMapper = new ObjectMapper();
    User user = objectMapper.readValue(emptyJson, User.class);

    // Validate default values
    assertEquals(0, user.id); // Default int value
    assertNull(user.name); // Null value
}

Best Practices for Test Coverage

  1. Positive Cases:
    • Serialization এবং Deserialization-এর জন্য সঠিক JSON এবং Object ব্যবহার করুন।
  2. Negative Cases:
    • Invalid JSON, Missing Fields, এবং Unknown Fields টেস্ট করুন।
  3. Boundary Conditions:
    • Null, Empty JSON, এবং Complex JSON হ্যান্ডল করুন।
  4. Custom Logic Testing:
    • Custom Serializer এবং Deserializer সঠিকভাবে কাজ করছে কিনা তা যাচাই করুন।
  5. Error Handling:
    • Exception Management সঠিকভাবে কাজ করছে কিনা তা নিশ্চিত করুন।

উপকারিতা

  • বাগ শনাক্তকরণ: Serialization এবং Deserialization সমস্যা দ্রুত শনাক্ত।
  • Reliable Code: API বা ডেটা প্রসেসিং সিস্টেম আরও নির্ভরযোগ্য।
  • Custom Logic Validation: Custom Serializer এবং Deserializer কার্যকারিতা নিশ্চিত।

এই পদ্ধতিগুলো অনুসরণ করে আপনি Jackson Serialization এবং Deserialization-এর জন্য শক্তিশালী Test Coverage তৈরি করতে পারবেন।

Content added By

Complex Object এর জন্য Unit Testing এবং Validation

219

Jackson ব্যবহার করে Complex Object-এর serialization, deserialization, validation এবং Unit Testing অত্যন্ত গুরুত্বপূর্ণ, বিশেষ করে RESTful API ডেভেলপমেন্টে। সঠিক টেস্টিং এবং ভ্যালিডেশন নিশ্চিত করলে ডেটার সঠিকতা এবং অ্যাপ্লিকেশনের নির্ভরযোগ্যতা বজায় থাকে।


Unit Testing এবং Validation এর ধাপসমূহ

  1. Setup for Unit Testing:
    • JUnit বা TestNG টেস্ট ফ্রেমওয়ার্ক ব্যবহার করুন।
    • Jackson-এর ObjectMapper ব্যবহার করে serialization/deserialization টেস্ট করুন।
  2. Data Validation:
    • Java Bean Validation (JSR 380) এর মাধ্যমে ডেটা যাচাই করুন।
    • কাস্টম validation এবং exception handling অন্তর্ভুক্ত করুন।
  3. Testing Complex Objects:
    • Nested objects এবং collections এর জন্য টেস্ট কেস তৈরি করুন।
    • JSON schema validation অন্তর্ভুক্ত করুন।

1. Maven Dependencies

JUnit এবং Jackson-এর জন্য নিম্নলিখিত ডিপেনডেন্সি যুক্ত করুন:

<dependencies>
    <!-- JUnit -->
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter</artifactId>
        <version>5.10.0</version>
        <scope>test</scope>
    </dependency>

    <!-- Jackson -->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.15.2</version>
    </dependency>

    <!-- Hibernate Validator -->
    <dependency>
        <groupId>org.hibernate.validator</groupId>
        <artifactId>hibernate-validator</artifactId>
        <version>8.0.0.Final</version>
    </dependency>
</dependencies>

2. Complex Object Model তৈরি করুন

import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;

import java.util.List;

public class Order {
    @NotNull(message = "Order ID cannot be null")
    private String orderId;

    @Valid
    @NotNull(message = "Customer cannot be null")
    private Customer customer;

    @Valid
    @NotNull(message = "Products cannot be null")
    private List<Product> products;

    // Getters and Setters
    public String getOrderId() { return orderId; }
    public void setOrderId(String orderId) { this.orderId = orderId; }

    public Customer getCustomer() { return customer; }
    public void setCustomer(Customer customer) { this.customer = customer; }

    public List<Product> getProducts() { return products; }
    public void setProducts(List<Product> products) { this.products = products; }
}

class Customer {
    @NotNull(message = "Customer Name cannot be null")
    @Size(min = 2, max = 50, message = "Customer Name must be between 2 and 50 characters")
    private String name;

    @NotNull(message = "Email cannot be null")
    private String email;

    // Getters and Setters
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }

    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }
}

class Product {
    @NotNull(message = "Product Name cannot be null")
    private String name;

    @NotNull(message = "Price cannot be null")
    private Double price;

    // Getters and Setters
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }

    public Double getPrice() { return price; }
    public void setPrice(Double price) { this.price = price; }
}

3. Unit Test Cases for Serialization and Deserialization

Serialization Test:

import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;

import java.util.Arrays;

import static org.junit.jupiter.api.Assertions.assertEquals;

class SerializationTest {

    @Test
    void testSerialization() throws Exception {
        ObjectMapper mapper = new ObjectMapper();

        Product product1 = new Product();
        product1.setName("Laptop");
        product1.setPrice(1200.50);

        Product product2 = new Product();
        product2.setName("Mouse");
        product2.setPrice(25.75);

        Customer customer = new Customer();
        customer.setName("Alice");
        customer.setEmail("alice@example.com");

        Order order = new Order();
        order.setOrderId("ORD123");
        order.setCustomer(customer);
        order.setProducts(Arrays.asList(product1, product2));

        String json = mapper.writeValueAsString(order);
        System.out.println("Serialized JSON: " + json);

        // Assert JSON contains key fields
        assertEquals(true, json.contains("ORD123"));
        assertEquals(true, json.contains("Laptop"));
        assertEquals(true, json.contains("Alice"));
    }
}

Deserialization Test:

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertNotNull;

class DeserializationTest {

    @Test
    void testDeserialization() throws Exception {
        ObjectMapper mapper = new ObjectMapper();

        String json = """
                      {
                          "orderId": "ORD123",
                          "customer": {
                              "name": "Alice",
                              "email": "alice@example.com"
                          },
                          "products": [
                              {
                                  "name": "Laptop",
                                  "price": 1200.50
                              },
                              {
                                  "name": "Mouse",
                                  "price": 25.75
                              }
                          ]
                      }
                      """;

        Order order = mapper.readValue(json, Order.class);

        // Assertions
        assertNotNull(order);
        assertNotNull(order.getCustomer());
        assertEquals(2, order.getProducts().size());
    }
}

4. Validation Test Cases

Validation Logic:

import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import org.junit.jupiter.api.Test;

import java.util.Arrays;
import java.util.Set;

import static org.junit.jupiter.api.Assertions.assertFalse;

class ValidationTest {

    private final Validator validator;

    public ValidationTest() {
        ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
        this.validator = factory.getValidator();
    }

    @Test
    void testValidationErrors() {
        Product product = new Product();
        product.setName("Laptop"); // Missing price

        Customer customer = new Customer();
        customer.setName("Alice");
        customer.setEmail(null); // Invalid email

        Order order = new Order();
        order.setOrderId("ORD123");
        order.setCustomer(customer);
        order.setProducts(Arrays.asList(product));

        Set<jakarta.validation.ConstraintViolation<Order>> violations = validator.validate(order);

        // Assert that validation errors exist
        assertFalse(violations.isEmpty());
        violations.forEach(violation -> System.out.println(violation.getMessage()));
    }
}

আউটপুট:

Price cannot be null
Email cannot be null

5. Exception Handling During Testing

Example of Handling Missing Fields:

@Test
void testMissingFields() {
    ObjectMapper mapper = new ObjectMapper();
    String invalidJson = """
                          {
                              "orderId": "ORD123",
                              "products": []
                          }
                          """;

    Exception exception = null;
    try {
        mapper.readValue(invalidJson, Order.class);
    } catch (Exception e) {
        exception = e;
    }

    assertNotNull(exception);
    System.out.println("Exception: " + exception.getMessage());
}

6. Schema Validation for Complex Objects

JSON Schema Validation:

@Test
void testJsonSchemaValidation() throws Exception {
    String schema = """
                    {
                        "$schema": "http://json-schema.org/draft-07/schema#",
                        "type": "object",
                        "properties": {
                            "orderId": {"type": "string"},
                            "customer": {
                                "type": "object",
                                "properties": {
                                    "name": {"type": "string"},
                                    "email": {"type": "string"}
                                },
                                "required": ["name", "email"]
                            },
                            "products": {
                                "type": "array",
                                "items": {
                                    "type": "object",
                                    "properties": {
                                        "name": {"type": "string"},
                                        "price": {"type": "number"}
                                    },
                                    "required": ["name", "price"]
                                }
                            }
                        },
                        "required": ["orderId", "customer", "products"]
                    }
                    """;

    String jsonData = """
                      {
                          "orderId": "ORD123",
                          "customer": {
                              "name": "Alice",
                              "email": "alice@example.com"
                          },
                          "products": [
                              {"name": "Laptop", "price": 1200.50}
                          ]
                      }
                      """;

    ObjectMapper mapper = new ObjectMapper();
    JsonSchemaFactory factory = JsonSchemaFactory.byDefault();
    JsonSchema jsonSchema = factory.getJsonSchema(mapper.readTree(schema));
    JsonNode data = mapper.readTree(jsonData);

    ProcessingReport report = jsonSchema.validate(data);
    assertTrue(report.isSuccess(), "Validation failed: " + report);
}

  1. Serialization/Deserialization Testing: Complex objects-এর জন্য নিশ্চিত

করুন JSON সঠিকভাবে প্রক্রিয়াজাত হচ্ছে।
2. Validation Testing: Nested objects এবং collections এর জন্য Bean Validation ব্যবহার করুন।
3. Error Handling: Exception Logging এবং Detailed Messages দিয়ে debugging সহজ করুন।
4. Schema Validation: JSON Schema দিয়ে JSON গঠন যাচাই করুন।

এই ধাপগুলো অনুসরণ করে আপনার Complex Object-এর জন্য নির্ভরযোগ্য এবং কার্যকর Unit Testing এবং Validation নিশ্চিত করা সম্ভব।

Content added By
Promotion
NEW SATT AI এখন আপনাকে সাহায্য করতে পারে।

Are you sure to start over?

Loading...